package com.basker.pisces.domain.property.meta;

import java.text.ParseException;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;

import com.basker.pisces.core.meta.IDataField;
import com.basker.pisces.core.meta.IDataObjectMeta;
import com.basker.pisces.core.meta.annotation.DataField;
import com.basker.pisces.core.meta.annotation.TimestampField.TimestampType;
import com.basker.pisces.domain.constant.DomainConstants.ObjectErrorCode;
import com.basker.pisces.domain.property.InvalidPropertyValueException;
import com.basker.pisces.domain.value.DateTimeValue;
import com.basker.pisces.resource.StringResources;
import com.basker.pisces.service.exception.IObjectErrorsWrapper.ObjectError;
import com.basker.pisces.utils.DateUtils;

public class DateTimeProperty extends Property<DateTimeValue> {

    @DataField
    private String format = DateUtils.DEFAULT_DATE_TIME;

    /**
     * 如果当前字段的原始类型是Long，该字段指明精度为毫秒还是秒
     */
    private transient TimestampType timestampType = TimestampType.Mills;

    @Override
    public void bindField(IDataObjectMeta objectMeta) {
        super.bindField(objectMeta);

        IDataField timestampField = objectMeta.getTimestampField();
        if (Objects.equals(this.field, timestampField)) {
            this.timestampType = objectMeta.getTimestampType();
        }
    }

    @Override
    public DateTimeValue createValue(Object rawValue) {
        rawValue = handleLongTypeValueIfNessary(rawValue);
        Date date = DateUtils.parse(rawValue);

        if (date == null) {
            return DateTimeValue.NULL_DATE;
        } else {
            return new DateTimeValue(date, format);
        }
    }

    public String getFormat() {
        return format;
    }

    public void setFormat(String format) {
        this.format = format;
    }

    @Override
    public void setValue(Object dataObject, Object inputValue) throws InvalidPropertyValueException {
        Date date = null;

        if (inputValue != null) {
            if (inputValue instanceof String) {
                try {
                    date = DateUtils.parse((String) inputValue, format);
                } catch (ParseException e) {
                    throw new InvalidPropertyValueException(Arrays.asList(new ObjectError(ObjectErrorCode.DATE_INVALID,
                            dataObject, "", this.getInvalidInputValueMessage(this.toString(), inputValue))));
                }
            } else {
                inputValue = handleLongTypeValueIfNessary(inputValue);
                date = DateUtils.parse(inputValue);
            }
        }

        this.setRawValue(dataObject, date);
    }

    @Override
    protected String getDefaultInvalidInputValueMessage(String propertyDesc, Object inputValue) {
        return StringResources.get("pisces-domain.DateTimeProperty.InvalidDate", propertyDesc, inputValue);
    }

    private Object handleLongTypeValueIfNessary(Object rawValue) {
        if (rawValue == null) {
            return rawValue;
        }

        if (this.timestampType.equals(TimestampType.Seconds)) {
            if (rawValue instanceof Long) {
                return ((Long) rawValue) * 1000;
            }
        }

        return rawValue;
    }

}
